//コマンドリストをパースする
//パックされたジオメトリコマンドを取得する（4バイト）
//1バイトずつ解体
//コマンド識別
#include "vert_color.h"

#define INFO_MAX	(32)

//頂点カラー情報
typedef struct VERT_COLOR_INFO_tag
{
	u16 DLOfs;
	u16 Color;
}VERT_COLOR_INFO;

typedef struct VERT_COL_DATA_tag
{
	u8 *DL;
	VERT_COLOR_INFO Info[INFO_MAX];
	u16 NowIdx;
	u16 Num;
}VERT_COL_DATA;

typedef struct VCOL_DATA_LIST_tag
{
	int Num;
	VERT_COL_DATA* Data;
}VCOL_DATA_LIST;

typedef struct CHG_WORK_tag
{
	u16 color;
	u16 count;
	VCDL_PTR vcdl;
}CHG_WORK;
static void TestChgColor(TCB_PTR tcb,void* work);


static u8 GetCmdParamLen(const u8 inCmd);
static void SetupInfo(const u32 inSize, VERT_COL_DATA *outData);


VCDL_PTR CreateVertColDataList(const int inHeapID, NNSG3dResShp *pResShp)
{
	u8 i;
	VCDL_PTR list;
	CHG_WORK *chg_work;

	list = sys_AllocMemory(inHeapID,sizeof(VCOL_DATA_LIST));
	list->Num = pResShp->dict.numEntry;
	list->Data = sys_AllocMemory(inHeapID,sizeof(VERT_COL_DATA)*list->Num);

	for(i=0;i<list->Num;i++){
		VERT_COL_DATA *data = &list->Data[i];
		const NNSG3dResShpData* shp;
		shp = NNS_G3dGetShpDataByIdx(pResShp, i);
		data->NowIdx = 0;
		data->Num = 0;
		data->DL = (u8*)shp + shp->ofsDL;
		SetupInfo(shp->sizeDL, data);
	}

	chg_work = sys_AllocMemory(inHeapID,sizeof(CHG_WORK));
	chg_work->color = 0;
	chg_work->count = 0;
	chg_work->vcdl = list;
	TCB_Add(TestChgColor, chg_work, 1);
///	ChangeColor(list);
	return list;
}

void FreeVertColDataList(VCDL_PTR ptr)
{
	sys_FreeMemoryEz(ptr->Data);
	sys_FreeMemoryEz(ptr);
}

//書き換え
void ChangeColor(VCDL_PTR ptr)
{
	u8 i,j;
	for(i=0;i<ptr->Num;i++){
		VERT_COL_DATA *data = &ptr->Data[i];
		for(j=0;j<data->Num;j++){
			data->DL[ data->Info[j].DLOfs ] = 0x7c1f/*0x1f*/;
		}
	}
}

//頂点カラー取得
void GetVertColor(VERT_COLOR_INFO *outVertColInfo, const u8 *inDL)
{
	;
}

static u8 GetCmdParamLen(const u8 inCmd)
{
	u8 prm_len;
	switch(inCmd){
	case G3OP_NOP:		/* Nop            */
		prm_len = G3OP_NOP_NPARAMS;
		break;
	case G3OP_BEGIN:	/* Begin          */
		prm_len = G3OP_BEGIN_NPARAMS;
		break;
	case G3OP_END:		/* End            */
		prm_len = G3OP_END_NPARAMS;
		break;
	case G3OP_COLOR:	/* Color          */
		prm_len = G3OP_COLOR_NPARAMS;
		break;
	case G3OP_NORMAL:	/* Normal         */
		prm_len = G3OP_NORMAL_NPARAMS;
		break;
	case G3OP_TEXCOORD:	/* TexCoord       */
		prm_len = G3OP_TEXCOORD_NPARAMS;
		break;
	case G3OP_VTX_16:	/* Vertex         */
		prm_len = G3OP_VTX_16_NPARAMS;
		break;
	case G3OP_VTX_10:	/* VertexShort    */
		prm_len = G3OP_VTX_10_NPARAMS;
		break;
	case G3OP_VTX_XY:   /* VertexXY       */
		prm_len = G3OP_VTX_XY_NPARAMS;
		break;
	case G3OP_VTX_XZ:   /* VertexXZ       */
		prm_len = G3OP_VTX_XZ_NPARAMS;
		break;
	case G3OP_VTX_YZ:   /* VertexYZ       */
		prm_len = G3OP_VTX_YZ_NPARAMS;
		break;
	case G3OP_VTX_DIFF: /* VertexDiff     */
		prm_len = G3OP_VTX_DIFF_NPARAMS;
		break;
	case G3OP_MTX_RESTORE:	/* RestoreMatrix  */
		prm_len = G3OP_MTX_RESTORE_NPARAMS;
		break;
	default:
		OS_Printf("unkown\n");
		prm_len = 0;
		break;
	}
	return prm_len;
}

static void SetupInfo(const u32 inSize, VERT_COL_DATA *outData)
{
	u8 cmd[4];
	u32 ofs;
	u8 i;
	u8 *dl;

	dl = outData->DL;
	ofs = 0;

	while(ofs < inSize){
		//ディスプレイリストからジオメトリコマンドを取得
		for (i=0;i<4;i++){
			cmd[i] = (u8)(*dl);
			dl++;
			ofs++;
		}
		for (i=0;i<4;i++){
			u8 len;
			if (cmd[i] == G3OP_COLOR){
				VERT_COLOR_INFO *info;
				info = &outData->Info[ outData->NowIdx++ ];
				//色情報を取得
				info->Color = *((u16*)dl);
				info->DLOfs = ofs;
				outData->Num++;
				OS_Printf("Color = %x\n",info->Color);
				if (outData->Num >= INFO_MAX){
					OS_Printf("OVER\n");
					return ;
				}
			}
			len = GetCmdParamLen(cmd[i]);
			dl += (len*4);
			ofs += (len*4);
		}
	}
}

static void TestChgColor(TCB_PTR tcb,void* work)
{
	u8 i,j;
	VCDL_PTR ptr;
	u16 *color;

	CHG_WORK* chg_work = (CHG_WORK*)work;


	ptr = chg_work->vcdl;
	if (chg_work->count >=30 ){
		for(i=0;i<ptr->Num;i++){
			VERT_COL_DATA *data = &ptr->Data[i];
			for(j=0;j<data->Num;j++){
				color = (u16*)&(data->DL[ data->Info[j].DLOfs ]);
				(*color) = chg_work->color;
			}
		}
		chg_work->color = (chg_work->color+0x10) % 0x8000;
		OS_Printf("color:%x\n",chg_work->color);
	}
	chg_work->count = (chg_work->count+1)%31;
}